/*
 * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.i360day.invoker;

import com.i360day.invoker.common.HttpInvokerRemoteConstant;
import com.i360day.invoker.http.Request;
import com.i360day.invoker.http.Response;
import com.i360day.invoker.properties.HttpInvokerProperties;
import com.i360day.invoker.request.HttpInvokerRequest;
import com.rabbitmq.client.AMQP;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;

import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author: liju.z
 * @date: 2024/3/18 13:38
 */
public class AmqpHttpInvokerRequest implements HttpInvokerRequest {
    private final String RPC_REPLY_KEY = "amqp.invoker.rpc.reply.%s";
    private final HttpInvokerProperties httpInvokerProperties;
    private final SimpleRabbitmqTemplate simpleRabbitmqTemplate;

    public AmqpHttpInvokerRequest(ConnectionFactory connectionFactory, HttpInvokerProperties httpInvokerProperties) {
        this.simpleRabbitmqTemplate = new SimpleRabbitmqTemplate(connectionFactory);
        this.httpInvokerProperties = httpInvokerProperties;
    }

    @Override
    public Response executor(RequestTemplate requestTemplate) throws IOException {
        Request request = requestTemplate.convertRequest();

        String replyTo = String.format(RPC_REPLY_KEY, UUID.randomUUID());
        return simpleRabbitmqTemplate.execute(channel -> {
            //回复
            try (DefaultMessageReply defaultMessageReply = new DefaultMessageReply(replyTo, channel)) {
                //发送
                AMQP.BasicProperties replyProperties = new AMQP.BasicProperties.Builder()
                        .correlationId(UUID.randomUUID().toString())
                        .replyTo(replyTo)
                        .headers(requestTemplate.getHeaders().keySet().stream().collect(Collectors.toMap(k -> k, v -> requestTemplate.getHeaders(v))))
                        .contentType(HttpInvokerRemoteConstant.ACCEPT_RPC_HTTP_INVOKER)
                        .contentEncoding(requestTemplate.getCharset().toString())
                        .messageId(UUID.randomUUID().toString())
//                            .appId(properties.getAppId())
//                            .clusterId(properties.getClusterId())
//                            .deliveryMode(properties.getDeliveryMode())
//                            .type(properties.getType())
//                            .userId(properties.getUserId())
                        .build();
                defaultMessageReply.sendMessage(HttpInvokerRemoteConstant.EXCHANGE_KEY, request.getUri().getPath(), replyProperties, request.body().getBody());

                //等待结果
                return defaultMessageReply.getResponse(httpInvokerProperties.getReadTimeout(), TimeUnit.MILLISECONDS, request);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }
}
